package com.czmc.smalldemo;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.res.AssetManager;
import android.os.Handler;
import android.os.Message;
import android.telephony.SmsManager;
import android.widget.Toast;

import net.wequick.small.Bundle;
import net.wequick.small.Small;

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


public class UpgradeManager {
    private static UpgradeManager ins;

    public static UpgradeManager ins(Context context){
        if (ins==null){
            synchronized (UpgradeManager.class){
                if (ins==null) {
                    ins = new UpgradeManager(context);
                }
            }
        }
        return ins;
    }
    private class UpdateInfo {
        public String packageName;
        public String downloadUrl;
    }

    private  class UpgradeInfo {
        public JSONObject manifest;
        public List<UpdateInfo> updates;
    }

    private interface OnResponseListener {
        void onResponse(UpgradeInfo info);
    }

    public interface OnUpgradeListener {
        void onUpgrade(boolean succeed);
    }

    private class ResponseHandler extends Handler {
        private OnResponseListener mListener;

        public ResponseHandler(OnResponseListener listener) {
            mListener = listener;
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    mListener.onResponse((UpgradeInfo) msg.obj);
                    break;
            }
        }
    }

    private ResponseHandler mResponseHandler;

    private Context mContext;

    public UpgradeManager(Context context) {
        mContext = context;
    }

    public void checkUpgrade(final OnUpgradeListener l) {
        requestUpgradeInfo(Small.getBundleVersions(), new OnResponseListener() {
            @Override
            public void onResponse(UpgradeInfo info) {
                if(info==null){
                    l.onUpgrade(true);
                }else {
                    upgradeBundles(info,
                            l);
                }
            }
        });
    }

    /**
     * @param versions
     * @param listener
     */
    private void requestUpgradeInfo(final Map versions, OnResponseListener listener) {
        System.out.println("czmcdata:"+new JSONObject(versions)); // this should be passed as HTTP parameters
        mResponseHandler = new ResponseHandler(listener);
        new Thread() {
            @Override
            public void run() {
                try {
                    // Example HTTP request to get the upgrade bundles information.
                    // Json format see http://wequick.github.io/small/upgrade/bundles.json
                    URL url = new URL("http://192.168.0.112:8080/DataTest/test/checkupgrade?versions="+new JSONObject(versions));
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    StringBuilder sb = new StringBuilder();
                    InputStream is = conn.getInputStream();
                    byte[] buffer = new byte[1024];
                    int length;
                    while ((length = is.read(buffer)) != -1) {
                        sb.append(new String(buffer, 0, length));
                    }
//                    String oldstr = getJson("bundle.json");
//                    JSONObject old = new JSONObject(oldstr);
                    JSONObject jo = new JSONObject(sb.toString());
                    System.out.println("czmcdata:"+jo.toString());
//                    if(old.getString("version").equals(jo.getJSONObject("manifest").getString("version"))) {
//                        Message.obtain(mResponseHandler, 1, null).sendToTarget();
//                        return;
//                    }
                    // Parse json
                    String status = jo.getString("status");
                    boolean need = jo.getBoolean("need");
                    if(status.equals("success") && !need){
                        Message.obtain(mResponseHandler, 1, null).sendToTarget();
                        return;
                    }
                    JSONObject mf = jo.has("manifest") ? jo.getJSONObject("manifest") : null;
                    JSONArray updates = jo.getJSONArray("updates");
                    int N = updates.length();
                    List<UpdateInfo> infos = new ArrayList<UpdateInfo>(N);
                    for (int i = 0; i < N; i++) {
                        JSONObject o = updates.getJSONObject(i);
                        UpdateInfo info = new UpdateInfo();
                        info.packageName = o.getString("pkg");
                        info.downloadUrl = o.getString("url");
                        infos.add(info);
                    }

                    // Post message
                    UpgradeInfo ui = new UpgradeInfo();
                    ui.manifest = mf;
                    ui.updates = infos;
                    Message.obtain(mResponseHandler, 1, ui).sendToTarget();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    private static class DownloadHandler extends Handler {
        private OnUpgradeListener mListener;

        public DownloadHandler(OnUpgradeListener listener) {
            mListener = listener;
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    mListener.onUpgrade((Boolean) msg.obj);
                    break;
            }
        }
    }

    private DownloadHandler mHandler;

    private void upgradeBundles(final UpgradeInfo info,
                                final OnUpgradeListener listener) {
        // Just for example, you can do this by OkHttp or something.
        mHandler = new DownloadHandler(listener);
        new Thread() {
            @Override
            public void run() {
                try {
                    // Update manifest
                    if (info.manifest != null) {
                        if (!Small.updateManifest(info.manifest, false)) {
                            Message.obtain(mHandler, 1, false).sendToTarget();
                            return;
                        }
                    }
                    // Download bundles
                    List<UpdateInfo> updates = info.updates;
                    for (UpdateInfo u : updates) {
                        // Get the patch file for downloading
                        net.wequick.small.Bundle bundle = Small.getBundle(u.packageName);
                        File file = bundle.getPatchFile();

                        // Download
                        URL url = new URL(u.downloadUrl);
                        HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
                        InputStream is = urlConn.getInputStream();
                        OutputStream os = new FileOutputStream(file);
                        byte[] buffer = new byte[1024];
                        int length;
                        while ((length = is.read(buffer)) != -1) {
                            os.write(buffer, 0, length);
                        }
                        os.flush();
                        os.close();
                        is.close();

                        // Upgrade
                        bundle.upgrade();
                    }

                    Message.obtain(mHandler, 1, true).sendToTarget();
                } catch (IOException e) {
                    e.printStackTrace();
                    Message.obtain(mHandler, 1, false).sendToTarget();
                }
            }
        }.start();
    }
    public String getJson(String fileName) {

        StringBuilder stringBuilder = new StringBuilder();
        try {
            AssetManager assetManager = mContext.getAssets();
            BufferedReader bf = new BufferedReader(new InputStreamReader(
                    assetManager.open(fileName)));
            String line;
            while ((line = bf.readLine()) != null) {
                stringBuilder.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return stringBuilder.toString();
    }
}